# download_service.py
import os
import re
import hashlib
import requests
from urllib.parse import urlparse
from datetime import datetime
from pathlib import Path
from concurrent.futures import ThreadPoolExecutor, as_completed
from flask import current_app
from extensions import db
from models import ProductDetail, ImageRecord
from config import headers
from extensions import image_path_format

IMAGE_FOLDER = Path("static/images")
IMAGE_FOLDER.mkdir(parents=True, exist_ok=True)
MAX_WORKERS = 5  # 最多并发下载数


def generate_unique_filename(url, content):
    """生成基于URL哈希和内容哈希的唯一文件名"""
    # 使用URL和内容的双重哈希确保唯一性
    url_hash = hashlib.md5(url.encode("utf-8")).hexdigest()[:8]
    content_hash = hashlib.md5(content).hexdigest()[:8]

    # 从原始URL提取文件名部分（如果有）
    path = urlparse(url).path
    original_name = os.path.basename(path)
    if original_name and original_name != "/":
        name_base, ext = os.path.splitext(original_name)
        # 清理文件名中的非法字符
        name_base = re.sub(r'[<>:"/\\|?*]', "_", name_base)
        # 如果原始扩展名不存在或不是图片扩展名，使用.jpg
        if not ext.lower() in [".jpg", ".jpeg", ".png", ".gif", ".webp"]:
            ext = ".jpg"
        filename = f"{name_base}_{url_hash}_{content_hash}{ext}"
    else:
        filename = f"image_{url_hash}_{content_hash}.jpg"

    return filename


def get_existing_image_path(image_url):
    """通过ImageRecord表检查URL是否已下载，返回有效本地路径"""
    with current_app.app_context():
        # 严格通过image_url查询记录
        record = ImageRecord.query.filter_by(image_url=image_url).first()
        if record:
            # 验证文件是否存在，不存在则清理无效记录
            if os.path.exists(record.local_path):
                return record.local_path
            else:
                db.session.delete(record)
                db.session.commit()
    return None


def download_single_image(image_url):
    if not image_url:
        return None, "无URL"

    # 先查数据库，有记录直接返回
    existing_path = get_existing_image_path(image_url)
    if existing_path:
        return existing_path, None

    # 数据库无记录才下载
    try:
        response = requests.get(image_url, headers=headers, timeout=10)
        if response.status_code == 200:
            # 生成基于内容和URL的唯一文件名
            filename = generate_unique_filename(image_url, response.content)
            local_path = IMAGE_FOLDER / filename

            # 检查是否已有相同哈希的文件（极低概率冲突）
            if not local_path.exists():
                with open(local_path, "wb") as f:
                    f.write(response.content)

            local_path = image_path_format(local_path)

            # 下载后立即创建记录，确保后续请求能查到
            with current_app.app_context():
                db.session.add(ImageRecord(image_url=image_url, local_path=local_path))
                db.session.commit()

            return local_path, None
        else:
            return None, f"HTTP错误 {response.status_code}"
    except Exception as e:
        return None, f"异常：{e}"


def download_images_async(current_app, detail_ids):
    with current_app.app_context():
        details = ProductDetail.query.filter(ProductDetail.id.in_(detail_ids)).all()
        records_to_add = []
        details_to_update = []

        for detail in details:
            img_url = detail.image_url
            if not img_url or img_url == "原链接无图":
                continue

            # 先查数据库，避免重复下载
            existing_path = get_existing_image_path(img_url)
            if existing_path:
                detail.local_image_path = existing_path
                details_to_update.append(detail)
                print(f"[复用] {img_url} -> {existing_path}")
                continue

            # 新图片才下载
            try:
                response = requests.get(img_url, headers=headers, timeout=10)
                if response.status_code == 200:
                    # 生成唯一文件名
                    filename = generate_unique_filename(img_url, response.content)
                    local_path = IMAGE_FOLDER / filename

                    # 保存文件（如果不存在）
                    if not local_path.exists():
                        with open(local_path, "wb") as f:
                            f.write(response.content)

                    local_path = image_path_format(local_path)
                    detail.local_image_path = local_path
                    details_to_update.append(detail)

                    records_to_add.append(
                        ImageRecord(
                            detail_id=detail.id,
                            image_url=img_url,
                            local_path=local_path,
                        )
                    )
                    print(f"[新增] {img_url} -> {local_path}")
            except Exception as e:
                print(f"[错误] {img_url}: {str(e)}")
                continue

        # 批量提交
        try:
            if details_to_update:
                db.session.bulk_update_mappings(
                    ProductDetail,
                    [
                        {"id": d.id, "local_image_path": d.local_image_path}
                        for d in details_to_update
                    ],
                )
            if records_to_add:
                db.session.bulk_save_objects(records_to_add)
            db.session.commit()
            print(
                f"[完成] 新增{len(records_to_add)}条，复用{len(details_to_update) - len(records_to_add)}条"
            )
        except Exception as e:
            db.session.rollback()
            print(f"[失败] {str(e)}")
